package it.unibo.refolding.pico;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.google.common.base.Preconditions;

public class SingleScriptSetup {
  public double initialMovementM; public double approachRampSizeM; public double approachVelocityMPerS;
  public double surfaceDelayS; public double retractionVelocityMPerS; public double retractionRampSizeM;
  public double parkingMovementM, parkingVelocityMPerS;
  public int count;

  public SingleScriptSetup() {
    initialMovementM = Double.NaN;
    approachRampSizeM = Double.NaN;
    approachVelocityMPerS = Double.NaN;
    surfaceDelayS = Double.NaN;
    retractionVelocityMPerS = Double.NaN;
    retractionRampSizeM = Double.NaN;
    parkingMovementM = Double.NaN;
    parkingVelocityMPerS = Double.NaN;
    // Note that nanoDriver's count is actually one less.
    count = 0;
  }
  
  public SingleScriptSetup indicateWhenUnchanged(SingleScriptSetup setup) {
    return new SingleScriptSetup(
      Double.doubleToLongBits(initialMovementM) == Double.doubleToLongBits(setup.initialMovementM) ? Double.NaN
        : setup.initialMovementM,
      Double.doubleToLongBits(approachRampSizeM) == Double.doubleToLongBits(setup.approachRampSizeM) ? Double.NaN
        : setup.approachRampSizeM,
      Double.doubleToLongBits(approachVelocityMPerS) == Double.doubleToLongBits(setup.approachVelocityMPerS) ? Double.NaN
        : setup.approachVelocityMPerS,
      Double.doubleToLongBits(surfaceDelayS) == Double.doubleToLongBits(setup.surfaceDelayS) ? Double.NaN
        : setup.surfaceDelayS,
      Double.doubleToLongBits(retractionVelocityMPerS) == Double.doubleToLongBits(setup.retractionVelocityMPerS) ? Double.NaN
        : setup.retractionVelocityMPerS,
      Double.doubleToLongBits(retractionRampSizeM) == Double.doubleToLongBits(setup.retractionRampSizeM) ? Double.NaN
        : setup.retractionRampSizeM,
        Double.doubleToLongBits(parkingVelocityMPerS) == Double.doubleToLongBits(setup.parkingVelocityMPerS) ? Double.NaN
          : setup.parkingVelocityMPerS,
      Double.doubleToLongBits(parkingMovementM) == Double.doubleToLongBits(setup.parkingMovementM) ? Double.NaN
        : setup.parkingMovementM,
      count == setup.count ? 0 : setup.count);
  }

  public SingleScriptSetup(double initialMovementM, double approachRampSizeM,
    double approachVelocityMPerS, double surfaceDelayS, double retractionVelocityMPerS,
    double retractionRampSizeM, double parkingVelocityMPerS, double parkingMovementM, int count) {
    Preconditions.checkArgument(
      Double.isNaN(surfaceDelayS) | surfaceDelayS >= PicoConstants.DEAD_TIME_S,
      "surfaceDelayS=%s is not at least %s", surfaceDelayS, PicoConstants.DEAD_TIME_S);
    Preconditions.checkArgument(count >= 0);
    this.initialMovementM = initialMovementM;
    this.approachRampSizeM = approachRampSizeM;
    this.approachVelocityMPerS = approachVelocityMPerS;
    this.surfaceDelayS = surfaceDelayS;
    this.retractionVelocityMPerS = retractionVelocityMPerS;
    this.retractionRampSizeM = retractionRampSizeM;
    this.parkingVelocityMPerS = parkingVelocityMPerS;
    this.parkingMovementM = parkingMovementM;
    this.count = count;
  }

  public void copyFrom(SingleScriptSetup setup) {
    initialMovementM = setup.initialMovementM;
    approachRampSizeM = setup.approachRampSizeM;
    approachVelocityMPerS = setup.approachVelocityMPerS;
    surfaceDelayS = setup.surfaceDelayS;
    retractionVelocityMPerS = setup.retractionVelocityMPerS;
    retractionRampSizeM = setup.retractionRampSizeM;
    parkingVelocityMPerS = setup.parkingVelocityMPerS;
    parkingMovementM = setup.parkingMovementM;
    count = setup.count;
  }
  
  @Override
  public String toString() {
    return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
  }
}
